Ext.EventObject = function()
{
	var E = Ext.lib.Event, clickRe = /(dbl)?click/,
	// safari keypress events for special keys return bad keycodes
	safariKeys =
	{
		3: 13, // enter
		63234: 37, // left
		63235: 39, // right
		63232: 38, // up
		63233: 40, // down
		63276: 33, // page up
		63277: 34, // page down
		63272: 46, // delete
		63273: 36, // home
		63275: 35
	},
	// normalize button clicks
	btnMap = Ext.isIE ?
	{
		1: 0,
		4: 1,
		2: 2
	} :
	{
		0: 0,
		1: 1,
		2: 2
	};

	Ext.EventObjectImpl = function( e )
	{
		if( e )
		{
			this.setEvent(e.browserEvent || e);
		}
	};

	Ext.EventObjectImpl.prototype =
	{
		/** @private */
		setEvent: function( e )
		{
			var me = this;
			if( e == me || (e && e.browserEvent) )
			{ // already wrapped
				return e;
			}
			me.browserEvent = e;
			if( e )
			{
				// normalize buttons
				me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
				if( clickRe.test(e.type) && me.button == -1 )
				{
					me.button = 0;
				}
				me.type = e.type;
				me.shiftKey = e.shiftKey;
				// mac metaKey behaves like ctrlKey
				me.ctrlKey = e.ctrlKey || e.metaKey || false;
				me.altKey = e.altKey;
				// in getKey these will be normalized for the mac
				me.keyCode = e.keyCode;
				me.charCode = e.charCode;
				// cache the target for the delayed and or buffered events
				me.target = E.getTarget(e);
				// same for XY
				me.xy = E.getXY(e);
			}
			else
			{
				me.button = -1;
				me.shiftKey = false;
				me.ctrlKey = false;
				me.altKey = false;
				me.keyCode = 0;
				me.charCode = 0;
				me.target = null;
				me.xy =
				[
				    0, 0
				];
			}
			return me;
		},

		stopEvent: function()
		{
			var me = this;
			if( me.browserEvent )
			{
				if( me.browserEvent.type == 'mousedown' )
				{
					Ext.EventManager.stoppedMouseDownEvent.fire(me);
				}
				E.stopEvent(me.browserEvent);
			}
		},

		preventDefault: function()
		{
			if( this.browserEvent )
			{
				E.preventDefault(this.browserEvent);
			}
		},
		stopPropagation: function()
		{
			var me = this;
			if( me.browserEvent )
			{
				if( me.browserEvent.type == 'mousedown' )
				{
					Ext.EventManager.stoppedMouseDownEvent.fire(me);
				}
				E.stopPropagation(me.browserEvent);
			}
		},

		getCharCode: function()
		{
			return this.charCode || this.keyCode;
		},

		getKey: function()
		{
			return this.normalizeKey(this.keyCode || this.charCode);
		},

		// private
		normalizeKey: function( k )
		{
			return Ext.isSafari ? (safariKeys[k] || k) : k;
		},

		getPageX: function()
		{
			return this.xy[0];
		},

		getPageY: function()
		{
			return this.xy[1];
		},

		getXY: function()
		{
			return this.xy;
		},
		getTarget: function( selector, maxDepth, returnEl )
		{
			return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
		},

		getRelatedTarget: function()
		{
			return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
		},

		getWheelDelta: function()
		{
			var e = this.browserEvent;
			var delta = 0;
			if( e.wheelDelta )
			{ /* IE/Opera. */
				delta = e.wheelDelta / 120;
			}
			else if( e.detail )
			{ /* Mozilla case. */
				delta = -e.detail / 3;
			}
			return delta;
		},

		within: function( el, related, allowEl )
		{
			if( el )
			{
				var t = this[related ? "getRelatedTarget" : "getTarget"]();
				return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
			}
			return false;
		}
	};

	return new Ext.EventObjectImpl();
}();